package main

import (
	"crypto/cipher"
	"fmt"
	"crypto/aes"
	"os"
	"regexp"
	"gopkg.in/gomail.v2"
	"net/url"
	"github.com/gin-gonic/gin"
	"github.com/gin-contrib/sessions/cookie"
	"time"
	"github.com/gin-contrib/sessions"
	"net/http"
	"github.com/spf13/viper"
	"strings"
)

type Util struct {
}

var (
	commonIV    = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
	c           cipher.Block
	emailRegexp = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
)

func NewUtil() *Util {
	return &Util{}
}

func init() {
	key := "UserManagerUserManagerUserManage"
	// 创建加密算法aes
	var err error
	c, err = aes.NewCipher([]byte(key))
	if err != nil {
		fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key), err)
		os.Exit(-1)
	}
	profile := ""
	for _, arg := range os.Args {
		if strings.HasPrefix(arg, "--profile") {
			profile = arg[len("--profile="):]
			break
		}
	}
	if profile == "" {
		profile = "dev"
	}
	viper.SetConfigFile(fmt.Sprintf("conf/application-%s.yml", profile))
	err = viper.ReadInConfig()
	if err != nil {
		fmt.Printf("配置文件加载异常:%s\n", err)
		os.Exit(-1)
	}
}

//加密
func (u *Util) Encrypt(plaintext string) string {
	cfb := cipher.NewCFBEncrypter(c, commonIV)
	ciphertext := make([]byte, len(plaintext))
	cfb.XORKeyStream(ciphertext, []byte(plaintext))
	return string(ciphertext)
}

//解密
func (u *Util) Decrypt(ciphertext string) string {
	cfbdec := cipher.NewCFBDecrypter(c, commonIV)
	plaintext := make([]byte, len(ciphertext))
	cfbdec.XORKeyStream(plaintext, []byte( ciphertext))
	return string(plaintext)
}

//检验邮箱格式是否正确
func (u *Util) IsEmail(email string) bool {
	if emailRegexp.MatchString(email) {
		return true
	}
	return false
}

//发送激活邮件
func (u *Util) SendMail(email string) error {
	mail := gomail.NewMessage()
	mail.SetAddressHeader("From", "piao_hao@sina.com", "anonymous") // 发件人
	mail.SetHeader("To", mail.FormatAddress(email, ""))
	mail.SetHeader("Subject", "UserManager sign_up")                              // 主题
	mail.SetBody("text/html",
		fmt.Sprintf("请及时激活账户, <a href = \"%s/active.html?token=%s\">设置账户密码</a>",
			viper.GetString("account.active_url"), url.QueryEscape(email)))       // 正文
	d := gomail.NewDialer("smtp.sina.com", 465, "piao_hao@sina.com", "howtodoit") // 发送邮件服务器、端口、发件人账号、发件人密码
	if err := d.DialAndSend(mail); err != nil {
		return err
	}
	return nil
}

//cors中间件
func (u *Util) CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
			return
		}
		c.Next()
	}
}

//session 中间件
func (u *Util) SessionMiddleware() gin.HandlerFunc {
	store := cookie.NewStore([]byte("secret"))
	store.Options(sessions.Options{
		MaxAge: int(30 * time.Minute), //30min
		Path:   "/",
	})
	return sessions.Sessions("customsession", store)

}

//异常拦截器
func (u *Util) ErrorMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Next()
		if len(c.Errors) > 0 {
			fmt.Printf("%x", c.Errors)
			c.String(http.StatusInternalServerError, "系统内部错误")
			return
		}
	}
}

//登录拦截器
func (u *Util) AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		if sessions.Default(c).Get(SessionKey) != nil {
			c.Next()
			return
		}
		c.String(http.StatusForbidden, "please login")
		c.Abort()
	}
}
